<?php
/*
Copyright (C) 2009 de Flotte Maxence

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
?>
<?php

//Génération d'un ZZG
function genZzG($label,$ZzG) {

	include './ZzO/std/Boot.php';
	include './ZzO/std/Main.php';

	//Si le label n'est pas un entier
		if(!is_numeric($label)) {
			$_infoLabel['type'] = str_replace(array('{','}'),'',strToLower($label));
			$_infoLabel['user'] = !empty($_SESSION['id'])?$_SESSION['id']:1;
			$_infoLabel['group'] = 1;
			$_infoLabel['id'] = 0;
			$_infoLabel['name'] = '';
			$_infoLabel['dateC'] = time();
			$_infoLabel['dateU'] = time();
			$_infoLabel['userW'] = 1;
			$_infoLabel['groupW'] = 1;
			$_infoLabel['otherW'] = 1;
			$_infoLabel['userR'] = 1;
			$_infoLabel['groupR'] = 1;
			$_infoLabel['otherR'] = 1;
			//Identifiant temporaire ?
				if(empty($_SESSION['tmpId']))
					$_SESSION['tmpId'] = 1;
				else
					$_SESSION['tmpId']++;
				$GLOBALS['tmpId'] = $_SESSION['tmpId'];
				
			//On récupère le puZZle
			//Conexion mysql
			$mySql = $GLOBALS['MySql'];
			$query = $mySql->query('SELECT name, ZzS FROM '.$GLOBALS['prefix'].'puzzle Where id="'.$_infoLabel['type'].'" and altPuzzle=1');
			$_puzzle = $query->fetch_assoc();
			//Si il n'y a pas de réponse on retourne une erreur
				if($_puzzle == null) {
		//plus tard on chargera un ZzS
					echo 'Erreur puzzle inconu';
					$mySql->close();
					exit();
				}
				$_infoLabel['puZZleName'] = $_puzzle['name'];
				$_infoLabel['ZzS'] = $_puzzle['ZzS'];
				
				
		}
	//Si label classique
		else {
			//On récupère les infos du label
				$mySql = $GLOBALS['MySql'];
				$query = $mySql->query('SELECT '.$GLOBALS['prefix'].'label.id as id, dateC, dateU, type, '.$GLOBALS['prefix'].'label.name as name, userR, userW, otherR, otherW, groupR, groupW, user, `group`, '.$GLOBALS['prefix'].'puzzle.name as puZZleName, ZzS FROM '.$GLOBALS['prefix'].'label inner join '.$GLOBALS['prefix'].'puzzle on '.$GLOBALS['prefix'].'label.type = '.$GLOBALS['prefix'].'puzzle.id  Where '.$GLOBALS['prefix'].'label.id='.$label.' and altPuzzle='.$_GET['altPuZZle']);
				$_infoLabel = $query->fetch_assoc();
				//Si il n'y a pas de réponse on retourne une erreur
					if($_infoLabel == null) {
			//chargement du ZzS
						loadZzS('ErrorUnknowLabel');
						$mySql->close();
						exit();
					}
			}
		
		$dir = './ZzG/'.$label;

	//Regrade si le dossier exist & on le creer si il n'existe pas
	if(!file_exists($dir))
		mkdir($dir);
// echo '<pre>',createStaticpuZZle($_puzzle['ZzS'],$_infoLabel);
	//On génère le puZZle
			//ob_start();
			$gen = createStaticpuZZle($_infoLabel);
			//Remblacement des balises <ZzO/>
			//$gen = ob_get_contents();
			//ob_end_clean();
//		 }
//echo "[START]".$gen."[END]";
		//On copie le $gen dans le fichier
			file_put_contents($ZzG, $gen);
//$open = fopen($ZzG, "w");
//fwrite($open, $gen);
//fclose($open);
		//On ajoute le fichier dans le fichier log
			//On creer le fichier log si il n'existe pas & on le récupère dans la variable $tree
				if(!file_exists('./ZzG/tree.log')) {
					$_tree['totalSize'] = 0;
					file_put_contents('./ZzG/tree.log', serialize($_tree));
				}
				else
					$_tree = unserialize(file_get_contents('./ZzG/tree.log'));
			//On  ajoute le nouveau fichier cache
				$fileSize = filesize($ZzG);
				$_tree[$ZzG] = $fileSize;
			//On incremente la taille total
				$_tree['totalSize'] += $fileSize;
			file_put_contents('./ZzG/tree.log', serialize($_tree));


		//On affiche le fichier cache
		include $ZzG;
		
		//Si le fichier lataille de la chache est rop grand, alors on fait le menage
		if($_tree['totalSize'] > $GLOBALS['MaxCacheSize']) {
			include './ZzL/cleanZzG.php';
			cleanZzG();
		}

}

function createStaticpuZZle($_label,&$php = null) {
	
	$ZzS = $_label['ZzS'];
	$GLOBALS['label_user'] = $_label['user'];
	$GLOBALS['label_group'] = $_label['group'];
	$GLOBALS['label_id'] = $_label['id'];
	$GLOBALS['label_name'] = $_label['name'];
	$GLOBALS['label_type'] = $_label['type'];
	$GLOBALS['label_dateC'] = $_label['dateC'];
	$GLOBALS['label_dateU'] = $_label['dateU'];
	$GLOBALS['label_userW'] = $_label['userW'];
	$GLOBALS['label_groupW'] = $_label['groupW'];
	$GLOBALS['label_otherW'] = $_label['otherW'];
	$GLOBALS['"label_userR'] = $_label['userR'];
	$GLOBALS['label_groupR'] = $_label['groupR'];
	$GLOBALS['label_otherR'] = $_label['otherR'];
	$GLOBALS['isStatic'] = true;

	$globals =  '
//Liste des variables globales
	$GLOBALS[\'label_user\'] = '.$_label['user'].';
	$GLOBALS[\'label_group\'] = '.$_label['group'].';
	$GLOBALS[\'label_id\'] = '.$_label['id'].';
	$GLOBALS[\'label_name\'] = \''.addSlashes($_label['name']).'\';
	$GLOBALS[\'label_type\'] = \''.$_label['type'].'\';
	$GLOBALS[\'label_dateC\'] = '.$_label['dateC'].';
	$GLOBALS[\'label_dateU\'] = '.$_label['dateU'].';
	$GLOBALS[\'label_userW\'] = '.$_label['userW'].';
	$GLOBALS[\'label_groupW\'] = '.$_label['groupW'].';
	$GLOBALS[\'label_otherW\'] = '.$_label['otherW'].';
	$GLOBALS[\'label_userR\'] = '.$_label['userR'].';
	$GLOBALS[\'label_groupR\'] = '.$_label['groupR'].';
	$GLOBALS[\'label_otherR\'] = '.$_label['otherR'].';
	$GLOBALS[\'isStatic\'] = false;

	
	if(!empty($_POST[\'tmpId\']))
		$GLOBALS[\'tmpId\'] = $_POST[\'tmpId\'];
	else {
		if(empty($_SESSION[\'tmpId\']))
			$_SESSION[\'tmpId\'] = 1;
		else
			$_SESSION[\'tmpId\']++;
		$GLOBALS[\'tmpId\'] = $_SESSION[\'tmpId\'];
	}';

	if($_GET['altPuZZle'] == 'true') {
	$verif = '
//On verifie que le label est accéssible en écriture
	if(!labelIsWritable()) {
		loadZzS(\'ErrorLimitedRight\');
		exit();
	}';
	}
	else {
	$verif = '
//On verifie que le label est accéssible en lecture
	if(!labelIsReadable()) {
		loadZzS(\'ErrorLimitedRight\');
		exit();
	}';
	}


	//Titre de la page
		//$labelName = $_label['name'];
		$tr = new ZzTranslation('puZZleName',null);
		$title = $tr->tr(addslashes($_label['puZZleName'])).': '.addSlashes($_label['name']);

	$return = '<?php
/*
	Fichier ZZG
	Généré le : '.date('d - m - Y').'
*/
//On vérifie l existance des sessions
	if(!isSet($_SESSION))
		exit();'.$globals.$verif.'
?>';

	$ZzS = str_replace("\n","",$ZzS);
	$ZzS = str_replace("\r","",$ZzS);
	$php = '
$page =	new page("page");';
	$php .= '
$page->setTitle(\''.$title.'\');';
	if(isSet($noStructure) and $noStructure)
		$php .=  '
$page->setNoStructure(\'true\');';
	//$ListObject = Array('page'=>array('main'=>$Page));
	$Cursor = 0;
	$_ZzO = array();

	while($Cursor < strlen($ZzS))
		$php .= convertInstruction($ZzS,$Cursor,$LastObjectCall, $_ZzO);

	$php .= 'echo $page->buildStaticpuZZle();';
	$php .= '
$GLOBALS[\'noCache\'] = $page->noCache;';

	ob_start();
		eval($php);
		$gen = ob_get_contents();
	ob_end_clean();
	//$return .= '//$GLOBALS[\'MySql\']->close();'."\n";
/*	 $return .= '?>';*/
	return $return.$gen;
}

function convertInstruction($ZzS,&$Cursor,&$LastObjectCall,&$_ZzO) {
	//On lit le type de l'instruction
	$Instruction = strtolower(readWord($ZzS,$Cursor));
//echo '"'.$Instruction.'"<br/>';
	//Create
	$return = null;
	if($Instruction == 'create') {
		//On recupère le nom de l'objet
		$Obj = strtolower(readWord($ZzS,$Cursor));
		//On recupère l'addresse du fichier à inclure
		if($Obj != 'page') {
			$file2include = preg_replace('!^(.*)_(a-z0-1-)*$!','$1',$Obj);
			$file2include = str_replace('_','/',$file2include);
			if(!array_key_exists($Obj,$_ZzO))
				$include = 'include_once(\'./ZzO/'.$file2include.'.php\');'."\n";
			else
				$include = '';
			$_ZzO[$Obj] = true;
		}
		else
			$include = '';
		$Name = strtolower(readWord($ZzS,$Cursor));
		if ($Name == 'named')
			$Name = strtolower(readWord($ZzS,$Cursor));
		$return = '
'.$include.'$'.$Name.' = new '.$Obj.'(\''.$Name.'\',$page,\''.$Obj.'\');'."\n".'$'.$Name.'->page = $page;';
		$LastObjectCall = $Name;
	}
	elseif($Instruction == 'add') {
		$Obj = strtolower(readWord($ZzS,$Cursor));
		if($Obj == 'on') {
			$Obj = $LastObjectCall;
		}
		else {
			$WOn = strtolower(readWord($ZzS,$Cursor));
			$LastObjectCall = $Obj;
		}
		$Where = strtolower(readWord($ZzS,$Cursor));
		$return = '
$'.$Where.'->AddObject2(\'inner\',$'.$Obj.');'."\n";
	}
	elseif($Instruction == 'set') {
		$WPropriety = strtolower(readWord($ZzS,$Cursor));
		if($WPropriety != 'property')
			$Propriety = 'set'.$WPropriety;
		else
			$Propriety = 'set'.strtolower(readWord($ZzS,$Cursor));
		$WOf = strtolower(readWord($ZzS,$Cursor));
		if($WOf != 'of') {
			$Obj = $LastObjectCall;
		}
		else {
			$Obj = strtolower(readWord($ZzS,$Cursor));
			$WAt = strtolower(readWord($ZzS,$Cursor));
			$LastObjectCall = $Obj;
		}

		$Value = readWord($ZzS,$Cursor);
		$return = '
$'.$Obj.'->'.addslashes($Propriety).'(\''.addslashes($Value).'\');'."\n";
	}
	elseif($Instruction == 'insert') {
		$Obj2Insert = strtolower(readWord($ZzS,$Cursor));
		$WOn = strtolower(readWord($ZzS,$Cursor));
		$WProperty = strtolower(readWord($ZzS,$Cursor));
		$Property = strtolower(readWord($ZzS,$Cursor));
		$WOf = strtolower(readWord($ZzS,$Cursor));
		$Obj = strtolower(readWord($ZzS,$Cursor));
		$return = '
$'.$Obj.'->AddObject2(\''.addslashes($Property).'\',$'.$Obj2Insert.');'."\n";
	}
	elseif($Instruction == 'associate') {
		$Obj = strtolower(readWord($ZzS,$Cursor));
		if($Obj == 'to') {
			$Obj = $LastObjectCall;
		}
		else {
			$WTo = strtolower(readWord($ZzS,$Cursor));
			$LastObjectCall = $Obj;
		}
		$WFlux = strtolower(readWord($ZzS,$Cursor));
		$Type = strtolower(readWord($ZzS,$Cursor));
		$Flux = readWord($ZzS,$Cursor);
		$return = '
$'.$Obj.'->AddFlux(\''.addslashes($Flux).'\',\''.addslashes($Type).'\');'."\n";
	}
	elseif($Instruction == 'open') {
		$TypePuzzle = strtolower(readWord($ZzS,$Cursor));
		$Puzzle = strtolower(readWord($ZzS,$Cursor));
		$WNamed = strtolower(readWord($ZzS,$Cursor));
		if($WNamed != 'named')
			$Name = $WNamed;
		else
			$Name = strtolower(readWord($ZzS,$Cursor));
			if($TypePuzzle == 'mysqlpuzzle') {
				$return = '
$'.$Name.' = new ZzPuzzle(\''.$Name.'\');'."\n$".$Name.'->setPuzzle(\''.addslashes($Puzzle).'\');'."\n";
			}
			$LastObjectCall = $Name;
	}
	elseif($Instruction == 'when') {
		$Obj = strtolower(readWord($ZzS,$Cursor));
		if($Obj == 'is')
			$Obj = $LastObjectCall;
		else {
			$LastObjectCall = $Obj;
			$WIs = strtolower(readWord($ZzS,$Cursor));
		}
		$Event = strtolower(readWord($ZzS,$Cursor));
		$toDo = strtolower(readWord($ZzS,$Cursor));	
		if($toDo == 'change') {
			$What = strtolower(readWord($ZzS,$Cursor));
			$WTo = strtolower(readWord($ZzS,$Cursor));
			$NewValue = readWord($ZzS,$Cursor);
			$Methode = 'WhenIs'.$Event.'Change'.$What;
			$return = '
$'.$Obj.'->'.$Methode.'('.$NewValue.');'."\n";
		}
		elseif($toDo == 'reload') {
			$Who = strtolower(readWord($ZzS,$Cursor));
			$Methode = 'WhenIs'.$Event.'Reload';
			$return = '
$'.$Obj.'->'.$Methode.'('.$Who.');'."\n";
		}
	}
	elseif($Instruction == 'comment' or $Instruction == '#') {
		while($ZzS[$Cursor] != ';')
			$Cursor++;
	}
	elseif($Instruction != ';' and $Instruction != null) { echo '<pre>Error #02:01 Instruction \''.$Instruction.'\' inconnue sur la ligne \''.$Instruction.' '.readWord($ZzS,$Cursor).' '.readWord($ZzS,$Cursor).' '.readWord($ZzS,$Cursor).'...\'</pre>'; exit(); return null; }
	return $return;
}


function readWord($ZzS,&$Cursor) {
	//Si c'est on a un point virgule
	if($ZzS[$Cursor] == ';') {
		$Cursor++;
		return ';';
	 }
	//Si c'est la fin du code
	if($ZzS[$Cursor] == "\0") {
		return "\0";
	}
	//Si le mot est un longstring
	if($ZzS[$Cursor] == '"') {
		$isLongString = true;
		$Cursor++;
	}
	else
		$isLongString = false;
	//Sinon on lit le mot
	$Word = null;
	while($ZzS[$Cursor] != "\n" AND $ZzS[$Cursor] != ' ' AND $ZzS[$Cursor] != ';' AND !$isLongString OR $ZzS[$Cursor] != '"' AND $isLongString) {
		$Word .= $ZzS[$Cursor];
		$Cursor++;
	}
	//Si il n'y a pas d'espace ou de \n après
	if($ZzS[$Cursor] != ';' OR $ZzS[$Cursor] != ' ')
		$Cursor++;
	//Si le mots est AND
	if(strtolower($Word) == 'and')
		return ';';
	return $Word;
}
?>